<template>
  <!-- 添加或修改商品信息对话框 -->
  <el-dialog
    :title="title"
    :visible="visiable"
    width="900px"
    append-to-body
    :close-on-click-modal="false"
    :close-on-press-escape="false"
    @close="cancel"
  >
    <el-form
      ref="form"
      :model="form"
      :rules="rules"
      label-width="100px"
      style="padding-right: 20px"
    >
      <el-form-item label="商品编号" prop="goodsCode">
        <el-input v-model="form.goodsCode" placeholder="请输入商品编号" />
      </el-form-item>
      <el-form-item label="货品名称" prop="goodsName">
        <el-input v-model="form.goodsName" placeholder="请输入货品名称" />
      </el-form-item>
      <el-form-item label="商品类别" prop="productCategoryId">
        <!-- <el-cascader
          v-model="form.productCategoryId"
          placeholder="请选择商品类别"
          :options="categoryList"
          :props="{ value: 'id', label: 'categoryName' }"
          clearable
        ></el-cascader> -->
        <treeselect
          v-model="form.productCategoryId"
          :options="categoryList"
          :normalizer="normalizer"
          placeholder="选择父级分类"
        />
      </el-form-item>
      <el-form-item label="商品价格" prop="goodsPrice">
        <el-input-number
          v-model="form.goodsPrice"
          :precision="2"
          :step="0.1"
          :min="0"
          placeholder="请输入商品价格"
        />
      </el-form-item>
      <el-form-item label="主图图片" prop="picPath">
        <!-- <el-input v-model="form.picPath" placeholder="请输入主图图片" /> -->
        <ImageUpload
          :value="form.picPath"
          :limit="1"
          @input="handleUploadSuccess"
        />
      </el-form-item>
      <el-form-item label="排序" prop="productSort">
        <el-input-number v-model="form.productSort" placeholder="请输入排序" />
      </el-form-item>
      <el-form-item label="商品总数量" prop="productTotal">
        <el-input-number
          v-model="form.productTotal"
          :min="0"
          placeholder="请输入商品总数量"
        />
      </el-form-item>
      <el-form-item label="产品内容" prop="detailHtml">
        <Editor
          :value="form.detailHtml"
          :height="400"
          @on-change="
            (e) => {
              form.detailHtml = e.html;
            }
          "
        />
      </el-form-item>

      <el-form-item label="商品规格" prop="specificationList">
        <ul class="specificationList-wrap">
          <li v-for="(item, idx) in specificationList" :key="idx">
            <el-input
              class="input-name"
              v-model="item.name"
              :autofocus="true"
              placeholder="请输入规格名称"
              @keyup.enter.native="addSpecification(idx)"
              @blur="addSpecification(idx)"
            />
            <el-tag
              v-for="(tag, index2) in item.values"
              :key="index2"
              closable
              size="large"
              :disable-transitions="false"
              @close="deleteSpecificationValue(idx, index2)"
            >
              {{ tag }}
            </el-tag>
            <el-input
              class="input-new-tag"
              :autofocus="true"
              v-model="item.value"
              v-if="item.visible"
              @keyup.enter.native="addSpecificationValue(idx)"
              @blur="addSpecificationValue(idx)"
            >
            </el-input>
            <el-button
              v-else
              class="button-new-tag"
              size="small"
              :disabled="item.name ? false : true"
              @click="showInput(idx)"
              >+ 规格值</el-button
            >
            <el-button
              v-if="specificationList.length > 1"
              type="text"
              icon="el-icon-delete"
              @click="deleteSpecification(idx)"
              >删除</el-button
            >
          </li>
        </ul>
        <el-button
          v-if="specificationList.length < 2"
          type="text"
          icon="el-icon-circle-plus"
          @click="addRow()"
          >添加一行</el-button
        >
      </el-form-item>

      <el-form-item label="规格明细" prop="goodsContent">
        <el-table
          ref="AdduceTableTableRef"
          :data="tableContentData"
          border="border"
          stripe
          size="medium"
          style="width: 100%"
        >
          <el-table-column
            v-for="item in tableHeadData"
            :key="item.prop"
            :prop="item.prop"
            align="center"
            show-overflow-tooltip
            :label="item.name"
          >
            <template slot-scope="scope">
              <div class="lx-hidden" v-if="item.prop === 'goodsPrice'">
                <el-input-number
                  v-model="scope.row[item.prop]"
                  :controls="false"
                  :min="0"
                  style="width: 100%"
                  placeholder="请输入价格"
                />
              </div>
              <div class="lx-hidden" v-else-if="item.prop === 'goodsCount'">
                <el-input-number
                  v-model="scope.row[item.prop]"
                  style="width: 100%"
                  :step-strictly="true"
                  :controls="false"
                  placeholder="请输入库存"
                ></el-input-number>
              </div>
              <div class="" v-else-if="item.prop === 'picPath'">
                <ImageUpload
                  :value="scope.row[item.prop]"
                  :isShowTip="false"
                  :showIcon="false"
                  listType="picture"
                  :limit="1"
                  @input="onChangeImg($event, scope.row)"
                />
              </div>
              <div v-else>
                <span>{{ scope.row[item.prop] }}</span>
              </div>
            </template>
          </el-table-column>
        </el-table>
      </el-form-item>
    </el-form>
    <div slot="footer" class="dialog-footer">
      <el-button type="primary" @click="submitForm">确 定</el-button>
      <el-button @click="cancel">取 消</el-button>
    </div>
  </el-dialog>
</template>

<script>
import {
  getGoods,
  addGoods,
  updateGoods,
  saveRecord,
} from "@/api/goodsManage/goods";
import { listCategory } from "@/api/goodsManage/category";
import Editor from "@/components/Editor";
import Treeselect from "@riophae/vue-treeselect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
import ImageUpload from "@/components/ImageUpload";

const form = {
  id: null,
  goodsCode: null,
  goodsName: null,
  productCategoryId: null,
  productCategoryName: null,
  goodsPrice: null,
  picPath: null,
  productSort: null,
  productTotal: null,
  productSales: null,
  detailHtml: null,
  recommendStatus: "0",
  publishStatus: "0",
  delFlag: null,
  createTime: null,
  updateTime: null,
  createUserId: null,
  updateUserId: null,
  attrList: [],
  skuList: [],
  deleteFlag: false,
};
// 规格添加
const addObj = {
  name: "",
  value: "",
  visible: false,
  values: [],
  new: false,
};

export default {
  name: "EditGoods",
  components: {
    Editor,
    Treeselect,
    ImageUpload,
  },
  props: {
    id: {
      type: Number,
      default: 0,
    },
    visiable: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      // isOpen: false,
      form: this._.cloneDeep(form),
      // 表单校验
      rules: {
        goodsCode: [
          { required: true, trigger: "blur", message: "请输入商品编号" },
        ],
        goodsName: [
          { required: true, trigger: "blur", message: "请输入货品名称" },
        ],
        detailHtml: [
          { required: true, trigger: "blur", message: "请输入产品内容" },
        ],
        productCategoryId: [
          {
            required: true,
            message: "请选择商品类别",
            trigger: "change",
          },
        ],
      },
      // 规格/动态表头
      specificationList: [
        { ...this._.cloneDeep(addObj), prop: "attr" + new Date().getTime() },
      ],
      mapList: [],
      tableContentData: [], // 生成后表中的数据
      categoryList: [],
      imgList: [],
      skuList: [],
      tableHeadData: [], // 表头
    };
  },
  computed: {
    title() {
      return this.id ? "编辑商品信息" : "添加商品信息";
    },
  },
  mounted() {
    this.$nextTick(() => {
      if (this.id) {
        this.getGoodsInfo(this.id);
      }
    });

    this.getProductCategoryData();
  },

  methods: {
    handleUploadSuccess(files) {
      let data = [];
      files.forEach((item) => {
        data.push(item.name);
      });
      this.imgList = data;
    },

    // 表格中默认 列
    staticData() {
      return [
        {
          name: "价格(元)",
          prop: "goodsPrice",
          value: "",
          require: true,
        },
        {
          name: "库存",
          prop: "goodsCount",
          value: "",
          require: true,
        },
        {
          name: "封面图",
          prop: "picPath",
          value: "",
          require: true,
        },
      ];
    },

    // 删除规格值
    deleteSpecificationValue(index, index2) {
      if (!this.tableContentData.length) {
        return this.specificationList[index].values.splice(index2, 1);
      }
      const length = this.specificationList[index].values.length;
      const title = this.specificationList[index].name;
      const delVal = this.specificationList[index].values[index2];
      const delProp = this.specificationList[index].prop;
      this.$confirm(`确定删除 ${title} 为：${delVal}的项吗？`, "系统提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          this.specificationList[index].values.splice(index2, 1);
          if (length > 1) {
            // 如果有多个值时就删除 this.tableContentData 中带有这个值的那一行
            for (let i = 0; i < this.tableContentData.length; i++) {
              if (this.tableContentData[i][delProp] === delVal) {
                this.tableContentData.splice(i, 1);
                i--; // 删除一行 从第一行开始寻找
              }
            }
          } else {
            // 如果只有一个值 那就把值从所有数据中删除 就是删除列
            this.specificationList[index].new = false;
            // this.deleteRowData(delProp, title);
            if (this.tableContentData.length === 0) {
              // 如果删除的是最后的规格和最后一个值就清空数据
              this.tableContentData = [];
              this.tableHeadData = [];
              this.specificationList.forEach((item) => (item.new = false));
              return false;
            }
          }
          // 重新生成表头
          this.generateTableHead();
        })
        .catch(() => {});
    },
    showInput(idx) {
      this.specificationList[idx].visible = true;
    },

    // 添加规格
    addSpecification(idx) {
      console.log(this.specificationList[idx]);
      let value = this.specificationList[idx].name;
      if (!value) {
        this.$message.warning("请填写规格名称");
        return false;
      }

      let staticSpecification = this.staticData().find(
        (item) => item.name === value
      );
      if (staticSpecification !== undefined) {
        this.$message.warning(`规格名称不能为${staticSpecification.name}`);
        this.specificationList[idx].name = "";
        return false;
      }
      let repetition = this.specificationList.some((item, index) => {
        if (idx !== index) {
          return item.name === value;
        }
      });
      if (repetition) {
        this.$message.warning("请勿重复添加规格");
        this.specificationList[idx].name = "";
        return false;
      }
      let flag = this.specificationList.some((item) => item.values.length > 0);
      if (!flag) return false;
      this.generateTableHead();
    },
    // 添加规格值
    addSpecificationValue(idx) {
      console.log(this.tableContentData);
      const value = this.specificationList[idx].value.trim();
      let list = this.specificationList[idx].values;
      if (list.some((item) => item.value === value)) {
        this.specificationList[idx].value = "";
        this.$message.warning("请勿重复规格值！");
        return false;
      }
      this.specificationList[idx].new =
        !this.specificationList[idx].values.length &&
        this.tableContentData.length
          ? true
          : false;
      if (value) {
        list.push(value);
      }
      this.specificationList[idx].value = "";
      this.specificationList[idx].visible = false;
      this.generateData(idx);
    },

    generateData(index) {
      if (!this.specificationList.length) return false;
      let flag = this.specificationList.some((item) => item.values.length > 0);
      if (!flag) return false;
      this.generateTableHead();
      this.generateTableContent(index);
    },

    // 生成表头
    generateTableHead() {
      this.tableHeadData = [];
      this.specificationList.forEach((item) => {
        if (item.values.length) {
          this.tableHeadData.push({
            name: item.name,
            prop: item.prop,
          });
        }
      });
      this.tableHeadData.push(...this.staticData().map((item) => item));
    },

    // 处理表格中的数据
    generateTableContent(idx) {
      const tempTitle = this.specificationList[idx].name;
      // 简单的深拷贝 不影响原始数据 然后过滤没有规格值的规格
      let tempList = JSON.parse(JSON.stringify(this.specificationList)).filter(
        (item) => item.values.length
      );

      const index = tempList.findIndex((item) => item.name === tempTitle);

      /**
       * idx 是 this.specificationList 中当前添加值的规格项的索引
       * index 是 tempList 中的索引 即this.specificationList筛选后对应的索引
       *
       */
      // newItem 为新添加的规格值项
      const newItem = tempList[index].values[tempList[index].values.length - 1];
      tempList[index].values = [newItem]; // 使用当前新添加的规格值的规格项中只有新添加的规格值 不然会出现重复数据
      const hasNewSpecificationItem = tempList.find((item) => item.new);

      /**
       * 如果当前添加的规格值的规格项是第一次添加值 那么它的 new 为true
       * hasNewSpecificationItem 就为当前的那一项
       * 此时表格中的每一行都需要添加一列新的规格数据 而不是需要重新组合生成数据
       *
       */

      if (hasNewSpecificationItem !== undefined) {
        for (let i = 0; i < this.tableContentData.length; i++) {
          console.log(
            "tableContentData hasNewSpecificationItem",
            this.tableContentData
          );
          //  如果 idx 和 index 不相等 证明出现没有值的规格 所以需要用筛选后的索引在表格中插入数据
          const spliceIndex =
            idx === index ? hasNewSpecificationItem.sort : index;

          // 表格中的都每行插入一列新的规格数据
          this.tableContentData[i][hasNewSpecificationItem.prop] =
            hasNewSpecificationItem.values[0];
          // 插入玩数据后 使 new 标记为false
          this.specificationList.forEach((item) => (item.new = false));
        }
      } else {
        // 修改数据结构
        const arr = tempList.map((item) => {
          return item.values.map((value) => {
            return {
              type: "sku",
              value: value,
              sort: item.sort,
              name: item.name,
              prop: item.prop,
            };
          });
        });

        // 数据改造成真正的表中的数据的结构
        const tableContentData = this.cartesianProductOf(...arr);
        let list = [];
        tableContentData.forEach((item, index) => {
          // 给表中每行加一些静态的数据 如输入框 下拉框等
          item.push(...this.staticData());
          let obj = {};
          item.forEach((sku) => {
            console.log(sku);
            obj[sku.prop] = sku.value;
          });
          list[index] = obj;
        });

        // 数据加入表格中
        this.tableContentData.push(...list);
      }
    },

    // 删除表中的一列
    deleteRowData(prop, title) {
      for (let i = 0; i < this.tableContentData.length; i++) {
        if (this.tableContentData[i][prop] == title) {
          this.tableContentData[i].splice(i, 1);
        }
      }
    },

    // 笛卡尔积
    cartesianProductOf() {
      return Array.prototype.reduce.call(
        arguments,
        function (a, b) {
          var ret = [];
          a.forEach(function (a) {
            b.forEach(function (b) {
              ret.push(a.concat(b));
            });
          });
          return ret;
        },
        [[]]
      );
    },

    addRow() {
      this.specificationList.push({
        ...this._.cloneDeep(addObj),
        prop: "attr" + new Date().getTime(),
      });
    },
    // 删除规格
    deleteSpecification(idx) {
      console.log(this.specificationList[idx]);
      let title = this.specificationList[idx].name;
      let prop = this.specificationList[idx].prop;
      this.$confirm(`确定删除规格名称为 ${title} 的项?`, "系统提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          const tempList = JSON.parse(JSON.stringify(this.specificationList)); // 删除之前先保存一份用于后面的判断
          this.specificationList.splice(idx, 1);
          if (!this.tableContentData.length) return false;
          // 如果删除的规格里面没有值就不用在 this.tableContentData 中删除数据
          if (!tempList[idx].values.length) return false;
          // 删除表中整列的数据
          // this.deleteRowData(prop, title);
          // 去重表格中重复的值
          for (let i = 0; i < this.tableContentData.length; i++) {
            let repeteRow = {};
            Object.keys(this.tableContentData[i]).map((key) => {
              if (key != prop && key.includes("attr")) {
                repeteRow[key] = this.tableContentData[i][key];
              }
            });

            for (let j = i + 1; j < this.tableContentData.length; j++) {
              let repeteRow2 = {};
              Object.keys(this.tableContentData[j]).map((key) => {
                if (key != prop && key.includes("attr")) {
                  repeteRow2[key] = this.tableContentData[j][key];
                }
              });
              if (JSON.stringify(repeteRow) == JSON.stringify(repeteRow2)) {
                this.tableContentData.splice(j, 1);
              }
            }
          }
          // 重新生成表头
          this.generateTableHead();
        })
        .catch(() => {});
    },

    onChangeImg(item, row) {
      console.log("onChangeImg", item, row);
      if (item.length) {
        row.picPath = item[0].url;
      } else {
        row.picPath = "";
      }
    },
    // 规格----end

    // 获取商品详情
    getGoodsInfo(id) {
      getGoods(id).then((response) => {
        let info = response.data;

        info.picPath = info.picPath ? info.picPath.split(",") : [];
        this.imgList = info.picPath;
        Object.keys(this.form).forEach((key) => {
          this.form[key] = info[key];
        });
        let attrList = info.attrList;
        let attrKey = [];
        if (attrList.length) {
          this.specificationList = [];
          attrList.forEach((item, index) => {
            attrKey[item.attrName] = "attr" + index;
            let obj = {
              name: item.attrName,
              prop: "attr" + index,
              value: "",
              visible: false,
              values: item.attrValue ? item.attrValue.split(",") : [],
            };
            this.specificationList.push(obj);
          });
        }

        let skuList = info.skuList;
        skuList.forEach((sku) => {
          let skuAttrData = JSON.parse(sku.goodsAttrs);
          let obj = { ...sku };
          skuAttrData.forEach((attr) => {
            for (var key in attr) {
              obj[attrKey[key]] = attr[key];
            }
          });
          this.tableContentData.push(obj);
        });
        this.generateTableHead();
      });
    },

    // 商品分类
    getProductCategoryData() {
      listCategory().then((response) => {
        this.categoryList = this.handleTree(response.data, "id", "pid");
      });
    },

    /** 转换分类数据结构 */
    normalizer(node) {
      if (node.children && !node.children.length) {
        delete node.children;
      }
      return {
        id: node.id,
        label: node.categoryName,
        children: node.children,
      };
    },

    /** 提交按钮 */
    submitForm() {
      let attrList = [];
      let attrNameList = [];
      let skuList = [];

      this.specificationList.forEach((item) => {
        if (item.name) {
          const obj = {
            attrName: item.name,
            attrValue: item.values ? item.values.join(",") : "",
            goodsld: null,
            id: null,
          };
          attrNameList[item.prop] = item.name;
          attrList.push(obj);
        }
      });
      this.tableContentData.forEach((item, index) => {
        let attrNames = [];
        for (const key in item) {
          if (attrNameList[key]) {
            attrNames.push({
              [attrNameList[key]]: item[key],
            });
          }
        }

        let obj2 = {
          ...item,
          goodsAttrs: attrNames.length ? JSON.stringify(attrNames) : "",
        };

        skuList.push(obj2);
      });
      this.form.attrList = attrList;
      this.form.skuList = skuList;
      this.form.picPath = this.imgList ? this.imgList.join(",") : "";
      console.log(skuList, attrList);
      // return false;
      this.$refs["form"].validate((valid) => {
        if (valid) {
          if (this.id) {
            saveRecord(this.form).then((res) => {
              if (res.code === 200) {
                this.$modal.msgSuccess("修改成功");
                this.$emit("confirm");
              }
            });
          } else {
            saveRecord(this.form).then((res) => {
              if (res.code === 200) {
                this.$modal.msgSuccess("新增成功");
                this.$emit("confirm");
              }
            });
          }
          setTimeout(() => {
            this.cancel();
          }, 300);
        }
      });
    },
    // 取消按钮
    cancel() {
      this.$emit("update:visiable", false);
      this.reset();
    },
    // 表单重置
    reset() {
      this.form = this._.cloneDeep(form);
      this.resetForm("form");
    },
  },
};
</script>

<style scoped>
ul,
li {
  margin: 0;
  padding: 0;
}
.specificationList-wrap li {
  margin-bottom: 15px;
}
.specificationList-wrap li:last-child {
  margin-bottom: 0;
}
.el-tag + .el-tag {
  margin-left: 10px;
}
.button-new-tag {
  margin-left: 10px;
  height: 32px;
  line-height: 30px;
  padding-top: 0;
  padding-bottom: 0;
}
.input-new-tag {
  width: 90px;
  margin: 0 10px;
  vertical-align: bottom;
}
.input-name {
  width: 150px;
  margin-right: 10px;
}
</style>
